/*
 * Copyright (C) 2022-2024 Huawei Device Co., Ltd.
 * Licensed under the MIT License, (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://opensource.org/licenses/MIT
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { References } from './References';
import HashMap from '@ohos.util.HashMap';
import ArrayList from '@ohos.util.ArrayList';
import { ListenerInfo } from '../entry/ListenerInfo';
import { Utils } from '../utils/Utils';
import { HandlerOptions } from './Handler';
import { MetadataReader } from './MetadataReader';
import { LogUtil } from '../../../../utils/LogUtil';

export namespace Annotations {
  const methodMap: HashMap<String | symbol, ArrayList<ListenerInfo>> =
    new HashMap<String | symbol, ArrayList<ListenerInfo>>();

  export function noticeHandleListener(msg: Object, methodName: String, listener) {
    var className = Utils.getClassName(listener);
    try {
      if (methodMap.hasKey(className)) {
        var methodArray = methodMap.get(className);
        methodArray.forEach((value, index) => {
          if (value.getMethodName() == methodName) {
            value.getMethodFun()(msg, listener);
            return;
          }
        })
      }
    } catch (e) {
      LogUtil.error(e);
    }
  }

  export function handle(handler?: HandlerOptions): MethodDecorator {
    return function (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) {
      var className = Utils.getClassName(target);
      var methodList: ArrayList<ListenerInfo>;
      if (methodMap.hasKey(className)) {
        methodList = methodMap.get(className);
      }
      if (!methodList) {
        methodList = new ArrayList<ListenerInfo>();
      }
      const sourceMethod = descriptor.value;

      descriptor.value = async function (...args: any) {
        await sourceMethod.apply(this, args);
      }
      var listener = new ListenerInfo();
      listener.setClassName(className);
      listener.setMethod(JSON.stringify(propertyKey), descriptor.value);
      methodList.add(listener);
      methodMap.set(className, methodList);
      MetadataReader.getInstance().setSubHandle(className, JSON.stringify(propertyKey), handler); //保存listener的方法注解的值
    }
  }


  export function Listener(className: String, reference: References): ClassDecorator {
    try {
      MetadataReader.getInstance().setListenerReferencesType(className, reference);
      LogUtil.debug(`Listener reference set for ${className}`);
      return (target: any) => {
        var className = Utils.getClassName(target);
      };
    } catch (e) {
      LogUtil.error(`Listener decorator failed: ${e.message}`);
    }
  }
}